package com.project.common.data.mybatis.provider;

import com.project.common.data.mybatis.provider.dm.DmCRUDProvider;
import com.project.common.data.mybatis.provider.mysql.MysqlCRUDProvider;
import com.project.common.exception.BusinessException;
import com.project.common.exception.ErrorCodes;
import org.apache.ibatis.builder.annotation.ProviderContext;

import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Enumeration;

public final class ProviderAdapter implements CRUDProvider {
    private static final String MYSQL_5_DRIVE_CLASS = "com.mysql.jdbc.Driver";
    private static final String MYSQL_8_DRIVE_CLASS = "com.mysql.cj.jdbc.Driver";
    private static final String DM_8_DRIVE_CLASS = "dm.jdbc.driver.DmDriver";
    public static final String ORACLE_6_DRIVE_CLASS = "oracle.jdbc.OracleDriver";
    public static final String ORACLE_DRIVE_CLASS = "oracle.jdbc.driver.OracleDriver";

    @Override
    public String insert(ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().insert(context);
    }

    @Override
    public String update(ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().update(context);
    }

    @Override
    public String updateSelective(Object entity, ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().updateSelective(entity, context);
    }

    @Override
    public String get(ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().get(context);
    }

    @Override
    public String listAll(ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().listAll(context);
    }

    @Override
    public String delete(ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().delete(context);
    }

    @Override
    public String deleteLogical(ProviderContext context) {
        return ProviderHolder.INSTANCE.getProvider().deleteLogical(context);
    }

    private enum ProviderHolder {
        INSTANCE;

        private CRUDProvider provider;

        ProviderHolder() {
            Enumeration<Driver> loadedDrives = DriverManager.getDrivers();
            while (loadedDrives.hasMoreElements()) {
                Driver driver = loadedDrives.nextElement();
                String className = driver.getClass().getName();
                if (MYSQL_5_DRIVE_CLASS.equals(className) || MYSQL_8_DRIVE_CLASS.equals(className)) {
                    this.provider = new MysqlCRUDProvider();
                    break;
                }
                if (DM_8_DRIVE_CLASS.equals(className)) {
                    this.provider = new DmCRUDProvider();
                }
            }
            if (this.provider == null) {
                throw new BusinessException(ErrorCodes.Common.ERROR_UNSUPPORTED_DATABASE.errorCode());
            }
        }

        public CRUDProvider getProvider() {
            return provider;
        }
    }
}
